import { Injectable } from '@nestjs/common';
import { OllamaService, OllamaMessage } from '../ollama/ollama.service';
import { ChatRequestDto, ChatResponseDto } from './dto/chat.dto';
import { ChatSessionService } from './chat-session.service';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable()
export class ChatService {
  constructor(
    private readonly ollamaService: OllamaService,
    private readonly chatSessionService: ChatSessionService,
  ) {}

  async chat(request: ChatRequestDto): Promise<ChatResponseDto> {
    let sessionId = request.sessionId;
    let session = null;

    // 如果有会话 ID，获取会话
    if (sessionId) {
      session = await this.chatSessionService.findById(sessionId);
    }

    // 如果没有会话，创建新会话
    if (!session) {
      const newSession = await this.chatSessionService.create({
        title: '新对话',
        model: request.model,
        messages: [],
      });
      session = newSession;
      sessionId = session._id.toString();
    }

    // 构建消息历史
    const messages: OllamaMessage[] = [];

    // 从数据库加载历史消息
    if (session.messages && session.messages.length > 0) {
      messages.push(
        ...session.messages.map((msg) => ({
          role: msg.role as 'user' | 'assistant' | 'system',
          content: msg.content,
        })),
      );
    }

    // 添加当前用户消息
    const userMessage = {
      role: 'user' as const,
      content: request.message,
      timestamp: new Date(),
    };
    messages.push({
      role: 'user',
      content: request.message,
    });

    // 保存用户消息到数据库
    await this.chatSessionService.addMessage(sessionId, userMessage);

    // 调用 Ollama API
    const response = await this.ollamaService.chat(request.model, messages, false);

    // 保存 AI 回复到数据库
    const assistantMessage = {
      role: 'assistant' as const,
      content: response,
      timestamp: new Date(),
    };
    await this.chatSessionService.addMessage(sessionId, assistantMessage);

    return {
      content: response,
      model: request.model,
      timestamp: new Date().toISOString(),
      sessionId: sessionId,
    };
  }

  /**
   * 流式聊天
   */
  chatStream(request: ChatRequestDto): Observable<string> {
    return new Observable((subscriber) => {
      let sessionId: string | null = null;
      let fullContent = '';
      let userMessageSaved = false;
      let assistantMessageSaved = false;

      (async () => {
        try {
          // 如果有会话 ID，获取会话
          if (request.sessionId) {
            const session = await this.chatSessionService.findById(request.sessionId);
            if (session) {
              sessionId = session._id.toString();
            }
          }

          // 如果没有会话，创建新会话
          if (!sessionId) {
            const newSession = await this.chatSessionService.create({
              title: '新对话',
              model: request.model,
              messages: [],
            });
            sessionId = newSession._id.toString();
            console.log(`📝 Created new session: ${sessionId}`);
          } else {
            console.log(`📝 Using existing session: ${sessionId}`);
          }

          // 构建消息历史
          const messages: OllamaMessage[] = [];

          // 从数据库加载历史消息
          const session = await this.chatSessionService.findById(sessionId);
          if (session && session.messages && session.messages.length > 0) {
            messages.push(
              ...session.messages.map((msg) => ({
                role: msg.role as 'user' | 'assistant' | 'system',
                content: msg.content,
              })),
            );
            console.log(`📚 Loaded ${session.messages.length} history messages`);
          }

          // 添加当前用户消息
          const userMessage = {
            role: 'user' as const,
            content: request.message,
            timestamp: new Date(),
          };
          messages.push({
            role: 'user',
            content: request.message,
          });

          // 保存用户消息到数据库
          try {
            const saved = await this.chatSessionService.addMessage(sessionId, userMessage);
            if (saved) {
              userMessageSaved = true;
              console.log(`✅ Saved user message to session ${sessionId}`);
            } else {
              console.error(`❌ Failed to save user message: returned null`);
            }
          } catch (saveError) {
            console.error(`❌ Error saving user message:`, saveError);
            console.error(`   Error details:`, JSON.stringify(saveError, null, 2));
            // 即使保存失败，也继续流式响应
          }

          // 发送会话 ID
          subscriber.next(JSON.stringify({ sessionId, type: 'session' }));

          // 流式调用 Ollama API
          let fullContent = '';
          try {
            for await (const chunk of this.ollamaService.chatStream(
              request.model,
              messages,
            )) {
              fullContent += chunk;
              subscriber.next(JSON.stringify({ content: chunk }));
            }

            // 保存完整的 AI 回复到数据库
            if (fullContent && sessionId) {
              const assistantMessage = {
                role: 'assistant' as const,
                content: fullContent,
                timestamp: new Date(),
              };
              try {
                const saved = await this.chatSessionService.addMessage(sessionId, assistantMessage);
                if (saved) {
                  assistantMessageSaved = true;
                  console.log(`✅ Saved assistant message to session ${sessionId}, content length: ${fullContent.length}`);
                } else {
                  console.error(`❌ Failed to save assistant message: returned null`);
                }
              } catch (saveError) {
                console.error(`❌ Error saving assistant message:`, saveError);
                console.error(`   Error details:`, JSON.stringify(saveError, null, 2));
                // 即使保存失败，也继续完成流式响应
              }
            } else {
              console.warn(`⚠️  No content to save or sessionId is null`);
            }

            // 发送完成信号
            subscriber.next(JSON.stringify({ done: true, sessionId }));
            subscriber.complete();
          } catch (streamError) {
            console.error(`❌ Error in stream:`, streamError);
            // 即使流式调用出错，也尝试保存已收集的内容
            if (fullContent) {
              try {
                const assistantMessage = {
                  role: 'assistant' as const,
                  content: fullContent,
                  timestamp: new Date(),
                };
                await this.chatSessionService.addMessage(sessionId, assistantMessage);
                console.log(`✅ Saved partial assistant message to session ${sessionId}`);
              } catch (saveError) {
                console.error(`❌ Error saving partial message:`, saveError);
              }
            }
            subscriber.error(streamError);
          }
        } catch (error) {
          console.error(`❌ Error in chatStream:`, error);
          subscriber.error(error);
        }
      })();
    });
  }
}

